# -*- coding: utf-8 -*-

from queue import Queue

class Prioridad:
###############################################################################################################

    # INICIALIZACION
    def __init__(self): 
        self.ready = Queue()
        self.currentTask = None
        self.manager = None
        self.dicPCBEnvejecimiento= {} # pcb, cantCiclosQueNoSeEjecuto 

    def __repr__(self):
        # Imprime las listas
        return ('Politica utilizada: Prioridad' )
       
###############################################################################################################

    # METODOS
     
    def actualTask(self):
        # Retorna la tarea actual
        return self.currentTask

    def nextTask(self): 
        # pide la siguiente tarea
        pcb = self.ready.get() # guarda la tarea, y la elimina de la cola
        del self.dicPCBEnvejecimiento[pcb] #borro el pcb del diccionario
        self.currentTask = pcb
        return pcb 
    
    def addTask(self, aTask): 
        # Agrega una tarea a la cola de listos
        print ('La prioridad q tengo es de %s' % aTask.getPriority())
        self.ready.put(aTask)
        self.dicPCBEnvejecimiento [aTask] = 0
        self.ordenarCola()
            
    def killTask(self):
        # Mata la tarea actual
        self.currentTask = None

    def hasNext(self):
        # Pregunta si existe una siguiente tarea
        return self.ready.qsize()> 0

    def listenCicloCpu(self):
        claves = self.dicPCBEnvejecimiento.keys() 
        for clave in claves: 
            self.dicPCBEnvejecimiento[clave] = self.dicPCBEnvejecimiento[clave] +1
        self.verificarEnvejecimiento ()
        
    def ordenarCola(self): 
        # Oedeno los elementos de la cola de listos, de mayor a menor. Asi se encuentran primero 
        # los de mayor prioridad.
        queueResultante = Queue ()
        while (not self.ready.empty()):
            maxx = self.elementoMaximo()
            queueResultante.put (maxx)
        self.ready = queueResultante
        
    def elementoMaximo (self):
        # Devuelve cual es la mayor prioridad de la cola de listos. 
        queue = Queue ()
        maxElem = self.ready.get ()
        while (not self.ready.empty()):
            elem = self.ready.get()
            if (maxElem.getPriority ()<= elem.getPriority()):
                queue.put (maxElem)
                maxElem = elem
            else:
                queue.put(elem)
        self.ready = queue
        return maxElem
        
    def verificarEnvejecimiento(self):
        claves = self.dicPCBEnvejecimiento.keys()
        for clave in claves:
            valor = self.dicPCBEnvejecimiento[clave] #cantidad de ciclos que no se ejecuto 
            print ('el pcb %s no se ejecuta hace %s instrucciones'% (clave.getProgram().getName(), valor))
            if valor>=5: # si cada 5 ciclos de cpu no se ejecuta, aumento la prioridad
                self.dicPCBEnvejecimiento[clave]=0 # al elemento lo seteo en 0
                print ('Anterior prioridad %s' % clave.getPriority())
                clave.incrementarPriority()
                print ('Actual prioridad %s' % clave.getPriority())
                self.ordenarCola()
            break
             
###############################################################################################################

    #GET&SET      
    def setManager(self, manager):
        self.manager = manager
    def getReady (self):
        return self.ready
    def setReady(self, readys):
        self.ready = readys    
